home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1996 March
/
EnigmA AMIGA RUN 05 (1996)(G.R. Edizioni)(IT)[!][issue 1996-03][Skylink CD IV].iso
/
earcd
/
dtype
/
fontdt10.lha
/
Src
/
dispatch.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-04-22
|
12KB
|
388 lines
/*
** dispatch.c - dispatcher for Font DataType class
** Copyright © 1995 Michael Letowski
*/
#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <dos/rdargs.h>
#include <graphics/displayinfo.h>
#include <graphics/gfx.h>
#include <graphics/modeid.h>
#include <graphics/rastport.h>
#include <graphics/text.h>
#include <intuition/classes.h>
#include <datatypes/datatypesclass.h>
#include <datatypes/pictureclass.h>
#include <diskfont/diskfont.h>
#include <diskfont/diskfonttag.h>
#include <utility/hooks.h>
#include <support/types.h>
#include <stdlib.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/diskfont.h>
#include <proto/datatypes.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <proto/utility.h>
#include <clib/support_protos.h>
#include "classbase.h"
#include "dispatch.h"
#include "prefs.h"
#include "otag.h"
#define COL_WHITE 0xFF
#define COL_BLACK 0x00
#define MAX_CHAR 257
/* Get font's name */
#define FontName(f) ((f)->tf_Message.mn_Node.ln_Name)
typedef int (SFUNC)(void const*, void const *);
STATIC ASM Object *Dispatch(R_A0 Class *cl, R_A2 Object *o, R_A1 Msg msg);
STATIC LBOOL GetFont(struct ClassBase *cb, Object *o, struct TagItem *attrs);
/* Font management */
STATIC struct TextFont **OpenFonts(struct ClassBase *cb,
struct FontContentsHeader *fch, STRPTR name);
STATIC VOID CloseFonts(struct ClassBase *cb, struct TextFont **f, ULONG cnt);
STATIC VOID GetWH(struct ClassBase *cb, struct RastPort *rp, struct Opts *opt,
struct TextFont *f, ULONG *w, ULONG *h);
STATIC VOID Render(struct ClassBase *cb, struct RastPort *rp, struct Opts *opt,
struct TextFont **f, ULONG cnt, ULONG w);
STATIC VOID MakeASCII(struct TextFont *f, CHAR *s);
STATIC VOID MakeFontName(struct TextFont *f, CHAR *s);
STATIC LONG SortFunc(struct TextFont **tf1, struct TextFont **tf2);
/* DataTypes stubs */
STATIC ULONG LocSetDTAttrs(struct ClassBase *cb, Object *o, ULONG data, ...);
STATIC ULONG LocGetDTAttrs(struct ClassBase *cb, Object *o, ULONG data, ...);
Class *InitClass(struct ClassBase *cb)
{
Class *CL;
/* Create our class (no instance) */
if(CL=MakeClass(FONTDTCLASS,PICTUREDTCLASS,NULL,NULL,0))
{
CL->cl_Dispatcher.h_Entry=(HOOKFUNC)Dispatch;
CL->cl_UserData=(ULONG)cb;
AddClass(CL);
}
return(CL);
} /* InitClass */
STATIC ASM Object *Dispatch(R_A0 Class *cl, R_A2 Object *o, R_A1 Msg msg)
{
struct ClassBase *cb=(struct ClassBase *)cl->cl_UserData;
Object *Obj;
switch(msg->MethodID)
{
case OM_NEW: /* We know this method */
if(Obj=(Object *)DoSuperMethodA(cl,o,msg))
unless(GetFont(cb,Obj,((struct opSet *)msg)->ops_AttrList))
{
CoerceMethod(cl,Obj,OM_DISPOSE);
return(NULL);
}
break;
default: /* Let the superclass handle it */
Obj=(Object *)DoSuperMethodA(cl,o,msg);
break;
}
return(Obj);
}
STATIC LBOOL GetFont(struct ClassBase *cb, Object *o, struct TagItem *attrs)
{
struct RastPort RP;
struct Opts Opts;
struct BitMapHeader *BMHD=NULL;
struct BitMap *BM;
struct ColorRegister *CMap=NULL;
LONG *CRegs=NULL;
struct FileInfoBlock *FIB;
struct FontContentsHeader *FCH;
struct TextFont **Fonts,*F;
struct ColorTextFont *CF;
struct ColorFontColors *CFC;
struct PrefsHandle *PH;
STRPTR Name=NULL,Title; /* Font file name & picture title */
BPTR DirLock,FH=0;
ULONG ModeID,SourceID; /* Display mode */
ULONG Width,Height,Depth,NumColors;
ULONG I,J,NumFonts;
LBOOL Tall,Wide,Result=FALSE;
UBYTE Col0,Col1;
/* Get default title */
Title=(STRPTR)GetTagData(DTA_Name,NULL,attrs);
/* Get file handle and BitMapHeader */
LocGetDTAttrs(cb,o,DTA_Handle,&FH,PDTA_BitMapHeader,&BMHD,TAG_DONE);
try(FH && BMHD, EXIT);
/* Get font file name */
try(FIB=AllocDosObject(DOS_FIB,NULL), NO_FIB);/* Create FileInfoBlock */
if(ExamineFH(FH,FIB)) /* Examine it */
Name=FIB->fib_FileName; /* Get name pointer */
else
if(Title) /* Get file part of title */
Name=FilePart(Title);
try(Name, NO_NAME);
/* Get font */
try(DirLock=ParentOfFH(FH), NO_LOCK);
try(FCH=NewFC(cb,DirLock,Name), NO_FCH);
try(Fonts=OpenFonts(cb,FCH,Name), NO_FONTS);
NumFonts=FCH->fch_NumEntries;
/* Read preferences */
PH=GetFontPrefs(cb,&Opts);
/* Calculate sizes */
Width=Height=0;
Depth=1;
InitRastPort(&RP); /* Set up RastPort - here! */
for(I=0; I<NumFonts; I++)
if(F=Fonts[I]) /* Opened successfully */
{
GetWH(cb,&RP,&Opts,F,&Width,&Height); /* Get width and height */
if(ftst(F->tf_Style,FSF_COLORFONT)) /* This is ColorFont */
{
CF=(struct ColorTextFont *)F;
if(CF->ctf_Depth>Depth) /* Deeper? */
Depth=CF->ctf_Depth; /* Set new depth */
}
Tall=ftst(F->tf_Flags,FPF_TALLDOT); /* Hires? */
Wide=ftst(F->tf_Flags,FPF_WIDEDOT); /* Interlaced? */
}
/* Set up BitMap header */
BMHD->bmh_Width=Width; /* Fill in informations */
BMHD->bmh_Height=Height;
BMHD->bmh_Depth=Depth;
NumColors=1<<Depth;
/* Get display mode id */
if(Tall && Wide) SourceID=HIRESLACE_KEY;
else if(Tall) SourceID=HIRES_KEY;
else if(Wide) SourceID=LORESLACE_KEY;
else SourceID=LORES_KEY;
ModeID=BestModeID(BIDTAG_DesiredWidth, Width,
BIDTAG_DesiredHeight, Height,
BIDTAG_Depth, Depth,
BIDTAG_SourceID, SourceID,
TAG_DONE);
/* Set colors */
LocSetDTAttrs(cb,o,PDTA_NumColors,NumColors,TAG_DONE);
LocGetDTAttrs(cb,o,PDTA_ColorRegisters,&CMap,PDTA_CRegs,&CRegs,TAG_DONE);
try(CMap && CRegs, ERROR);
if(Depth==1) /* B&W font */
{
Col0=Opts.opt_Inverse ? COL_BLACK : COL_WHITE;
Col1=Opts.opt_Inverse ? COL_WHITE : COL_BLACK;
CMap[0].red=CMap[0].green=CMap[0].blue=Col0;
CMap[1].red=CMap[1].green=CMap[1].blue=Col1;
CRegs[0]=CRegs[1]=CRegs[2]=Col0<<24;
CRegs[3]=CRegs[4]=CRegs[5]=Col1<<24;
}
else /* Some color fonts */
for(I=0; I<NumFonts; I++)
if(F=Fonts[I])
if(ftst(F->tf_Style,FSF_COLORFONT))
{
CF=(struct ColorTextFont *)F;
if(CFC=CF->ctf_ColorFontColors) /* Color map exists */
for(J=0; J<CFC->cfc_Count; J++)
{
CMap[J].red= (CFC->cfc_ColorTable[J] & 0x0F00)>>4;
CRegs[J*3+0]= CMap[J].red<<24;
CMap[J].green= (CFC->cfc_ColorTable[J] & 0x00F0);
CRegs[J*3+1]= CMap[J].green<<24;
CMap[J].blue= (CFC->cfc_ColorTable[J] & 0x000F)<<4;
CRegs[J*3+2]= CMap[J].blue<<24;
}
}
/* Prepare bitmap */
try(BM=AllocBitMap(BMHD->bmh_Width,BMHD->bmh_Height,BMHD->bmh_Depth,
BMF_CLEAR | BMF_INTERLEAVED,NULL),
ERROR);
/* Do rendering */
RP.BitMap=BM; /* Attach BitMap */
Render(cb,&RP,&Opts,Fonts,NumFonts,Width);
/* Set attributes of destination picture */
LocSetDTAttrs(cb,o,DTA_ObjName, Title,
DTA_NominalHoriz, BMHD->bmh_Width,
DTA_NominalVert, BMHD->bmh_Height,
PDTA_BitMap, BM,
PDTA_ModeID, ModeID,
TAG_DONE);
Result=TRUE;
/* Cleanup */
except(ERROR, );
if(PH)
FreeFontPrefs(cb,PH);
except(NO_FONTS, CloseFonts(cb,Fonts,NumFonts));
except(NO_FCH, DisposeFC(cb,FCH));
except(NO_LOCK, UnLock(DirLock));
except(NO_NAME, );
except(NO_FIB, FreeDosObject(DOS_FIB,FIB));
except(EXIT, );
return(Result);
} /* GetFont */
/****************************************************************************/
/* Font management */
/****************************************************************************/
STATIC struct TextFont **OpenFonts(struct ClassBase *cb,
struct FontContentsHeader *fch, STRPTR name)
{
struct TextFont **Fonts;
struct TFontContents *TFC;
struct TTextAttr TTA;
ULONG I,NumEntries=fch->fch_NumEntries;
LBOOL One=FALSE; /* Got at least one size */
try(Fonts=AllocVec(NumEntries*sizeof(APTR),MEMF_CLEAR), NO_FONTS);
for(I=0; I<NumEntries; I++)
{
TFC=&TFontContents(fch)[I]; /* Get FontContents */
TTA.tta_Name=name; /* Copy attrs */
TTA.tta_YSize=TFC->tfc_YSize;
TTA.tta_Style=TFC->tfc_Style;
TTA.tta_Flags=TFC->tfc_Flags;
if(ftst(TFC->tfc_Style,FSF_TAGGED)) /* Tags should be set */
TTA.tta_Tags=(struct TagItem *)
&TFC->tfc_FileName
[MAXFONTPATH-(TFC->tfc_TagCount*sizeof(struct TagItem))];
if(Fonts[I]=OpenDiskFont((struct TextAttr *)&TTA))
One=TRUE;
}
if(One) /* Got at least one font */
{ /* Sort by size */
qsort(Fonts,NumEntries,sizeof(APTR),(SFUNC *)SortFunc);
return(Fonts);
}
else
SetIoErr(ERROR_OBJECT_NOT_FOUND); /* Set error */
except(NO_FONTS, FreeVec(Fonts));
return(NULL);
} /* OpenFonts */
STATIC VOID CloseFonts(struct ClassBase *cb, struct TextFont **f, ULONG cnt)
{
ULONG I;
for(I=0; I<cnt; I++)
if(f[I])
CloseFont(f[I]);
FreeVec(f);
} /* CloseFonts */
STATIC VOID GetWH(struct ClassBase *cb, struct RastPort *rp, struct Opts *opt,
struct TextFont *f, ULONG *w, ULONG *h)
{
STRPTR DefStrings[]={NULL,NULL};
STRPTR CurStr,*Strings;
CHAR S[MAX_CHAR];
ULONG W;
SetFont(rp,f);
DefStrings[0]=S;
if(opt->opt_FontName && FontName(f))
MakeFontName(f,S); /* String=name+size */
else
MakeASCII(f,S); /* Prepare default string */
Strings=opt->opt_Strings ? opt->opt_Strings : DefStrings;
while(CurStr=*Strings++)
{
W=TextLength(rp,CurStr,strlen(CurStr)); /* Calculate len of this line */
if(W>*w) /* If larger... */
*w=W; /* Make it new width */
*h+=f->tf_YSize; /* Add to height */
}
} /* GetWidth */
STATIC VOID Render(struct ClassBase *cb, struct RastPort *rp, struct Opts *opt,
struct TextFont **f, ULONG cnt, ULONG w)
{
struct TextFont *F;
STRPTR DefStrings[]={NULL,NULL};
STRPTR CurStr,*Strings;
CHAR S[MAX_CHAR];
ULONG I,X,Y=0;
DefStrings[0]=S;
for(I=0; I<cnt; I++) /* For each font size */
if(F=f[I]) /* Size opened? */
{
SetFont(rp,F); /* Make it current font */
if(opt->opt_FontName && FontName(F))
MakeFontName(F,S); /* Prepare name+size */
else
MakeASCII(F,S); /* Prepare default string */
Strings=opt->opt_Strings ? opt->opt_Strings : DefStrings;
while(CurStr=*Strings++)
{
X=opt->opt_Center ? (w-TextLength(rp,CurStr,strlen(CurStr)))/2 : 0;
Move(rp,X,Y+F->tf_Baseline);
Text(rp,CurStr,strlen(CurStr));
Y+=F->tf_YSize;
}
}
} /* Render */
STATIC VOID MakeASCII(struct TextFont *f, CHAR *s)
{
ULONG I;
memset(s,0,MAX_CHAR); /* Clear string */
for(I=f->tf_LoChar; I<=f->tf_HiChar; I++)
s[I - f->tf_LoChar]=I; /* Make ASCII array */
} /* MakeASCII */
STATIC VOID MakeFontName(struct TextFont *f, CHAR *s)
{
SNPrintf(s,MAX_CHAR-1,"%s %ld",FontName(f),f->tf_YSize);
} /* MakeASCII */
STATIC LONG SortFunc(struct TextFont **tf1, struct TextFont **tf2)
{
if(*tf1 && *tf2) return((LONG)(*tf1)->tf_YSize - (*tf2)->tf_YSize);
else if(*tf1) return(-1);
else if(*tf2) return(1);
else return(0);
} /* SortFunc */
/****************************************************************************/
/* DataTypes stubs */
/****************************************************************************/
STATIC ULONG LocSetDTAttrs(struct ClassBase *cb, Object *o, ULONG data, ...)
{
return(SetDTAttrsA(o,NULL,NULL,(struct TagItem *)&data));
} /* LocSetDTAttrs */
STATIC ULONG LocGetDTAttrs(struct ClassBase *cb, Object *o, ULONG data, ...)
{
return(GetDTAttrsA(o,(struct TagItem *)&data));
} /* LocGetDTAttrs */